package com.zy.edu.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.zy.edu.bean.*;
import com.zy.edu.config.SystemParam;
import com.zy.edu.config.jwt.JwtHelper;
import com.zy.edu.config.jwt.JwtProperty;
import com.zy.edu.dao.UserDao;
import com.zy.edu.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zy.edu.util.FileUpload;
import com.zy.edu.util.Md5Util;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;

import static com.zy.edu.config.SystemParam.TOKENMAP;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author HuangHaiShui
 * @since 2021-07-13
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    @Resource
    JwtProperty jwtProperty;

    @Resource
    ClassinfoService classinfoService;

    @Resource
    SchoolService schoolService;

    @Resource
    JurisdictionService jurisdictionService;

    @Resource
    UserClassService userClassService;

    @Resource
    LogService logService;

    @Override
    public Map oauth(String account, String password) {
        if(StringUtils.isEmpty(password) ||StringUtils.isEmpty(password)){
            return ResponseInfo.error("账号或密码为空");
        }
        List<User> tempList = this.baseMapper.selectList(new EntityWrapper<User>()
                .eq("account", account)
                .eq("password", Md5Util.getMD5(password))
                .eq("status", 1)
            );
        if(tempList.size()>0){
            User user = tempList.get(0);
            String accessToken = "bearer " + JwtHelper.createJWT(account, user.getId(),
                    user.getRoleType(),  jwtProperty.getBase64Secret());
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("userId", user.getId());
            resultMap.put("token", accessToken);
            //登录成功，存入新token
            TOKENMAP.put(user.getId(),accessToken);
            //插入登录日志
            Log log = new Log();
            log.setCreateTime(new Date());
            log.setJurisId(user.getJurisId());
            log.setUserId(user.getId());
            log.setMethod("login");
            logService.insert(log);
            return ResponseInfo.success(resultMap);
        }else{
            return ResponseInfo.error("账号或密码错误");
        }
    }


    @Override
    public Map saveOrUpdate(User user,InputParam inputParam) {
        List<User> tempList = this.baseMapper.selectList(new EntityWrapper<User>()
                .eq("account", user.getAccount()));

        //若是学生的编辑功能
        if(!StringUtils.isEmpty(inputParam.getClassId())
                && user.getRoleType().equals(Role.STUDENT)){
            //学生编辑的时候，从班级取校区以及辖区
            Classinfo classinfo = classinfoService.selectById(inputParam.getClassId());
            if(classinfo!=null) {
                user.setClassId(inputParam.getClassId());
                user.setSchoolId(classinfo.getSchoolId());
                user.setJurisId(classinfo.getJurisId());
            }
        }

        if(StringUtils.isEmpty(user.getId())){
            user.setId("u-"+UUID.randomUUID().toString().replaceAll("-",""));
            user.setCreateTime(new Date());
            user.setStatus(1);
            if(StringUtils.isEmpty(user.getPassword())){
                user.setPassword(Md5Util.getMD5("123456"));
            }else{
                if(user.getPassword().length()>16){
                    return ResponseInfo.error("密码长度不能超过16位");
                }
                user.setPassword(Md5Util.getMD5(user.getPassword()));
            }
            if(tempList.size()>0){
                if(tempList.get(0).getStatus()==0){
                    return ResponseInfo.error("与已有的失效账号同名，不能创建");
                }else {
                    return ResponseInfo.error("账号已存在，不能创建");
                }
            }else {
                //设置关联学校
                if(!StringUtils.isEmpty(inputParam.getSchoolId())){
                    user.setSchoolId(inputParam.getSchoolId());
                }
                //设置关联辖区
                if(!StringUtils.isEmpty(inputParam.getJurisId())){
                    user.setJurisId(inputParam.getJurisId());
                }
                //设置关联班级 只有学生才直接关联
                this.baseMapper.insert(user);
                //老师是一对多，另外关联
                if(user.getRoleType().equals(Role.TEACHER)
                        && !StringUtils.isEmpty(inputParam.getClassId())){
                    addUserClass(inputParam,user.getId());
                }
            }
        }else{
            // 若存在账号相同的用户，且不是自己，则提示重复
            if(tempList.size()>0 && !tempList.get(0).getId().equals(user.getId())){
                return ResponseInfo.error("账号名已存在，不能修改");
            }else {

                //若是老师先删除所有关联，再重新写入
                userClassService.delete(new EntityWrapper<UserClass>()
                        .eq("uid", user.getId()));
                //根据不同的角色，再创建不同的关联
                if(user.getRoleType().equals(Role.TEACHER)
                        && !StringUtils.isEmpty(inputParam.getClassId())){
                    addUserClass(inputParam,user.getId());
                    user.setClassId(null);
                }
                this.baseMapper.updateById(user);
            }
        }
        return ResponseInfo.success(null);
    }

    /**
     * @Author: HuangHaiShui
     * @Description: 添加老师与班级的关联数据
     * @Date: 17:06 2021/7/16
     * @param inputParam: classId  老师的班级数据，多个用逗号隔开
     * @param teacherId: 老师id
     * @return: void
     **/
    private void addUserClass(InputParam inputParam,String teacherId ){
        String[] cidArr = inputParam.getClassId().split(",");
        for (String s : cidArr) {
            if(s.length()>2) {
                UserClass uc = new UserClass();
                uc.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                uc.setUid(teacherId);
                uc.setCid(s);
                userClassService.insert(uc);
            }
        }
    }

    /**
     * @Author: HuangHaiShui
     * @Description:
     * @Date: 17:30 2021/7/16
     * @param user:  roleType 表示要作哪个角色的查询
     * @param inputParam: userid 当前用户的id
     * @return: Map
     **/
    @Override
    public Map list(User user, InputParam inputParam) {

        //当前用户的信息
        User temp = this.baseMapper.selectById(inputParam.getUserId());

        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();
        if(!StringUtils.isEmpty(user.getName())){
            entityWrapper.like("name",user.getName());
        }

        //根据使用用户的角色，初始对应的查询条件
        if(!StringUtils.isEmpty(user.getRoleType())){
            entityWrapper.eq("role_type",user.getRoleType());
            if(temp.getRoleType().equals(Role.SUPER)){
                //若是超管，查所有人
            }else if(temp.getRoleType().equals(Role.AREA)){
                //若是区管，查辖区
                entityWrapper.eq("juris_id",temp.getJurisId());
            }else if(temp.getRoleType().equals(Role.SCHOOL)){
                //若是校管，查学校所有人
                entityWrapper.eq("school_id",temp.getSchoolId());
            }else if(temp.getRoleType().equals(Role.TEACHER)){
                //若是老师，查班级所有人
                //先查询老师的所有下属班级
                List<UserClass> classList = userClassService.selectList(new EntityWrapper<UserClass>()
                        .eq("uid", inputParam.getUserId()));
                if(classList.size()>0){
                    ArrayList<String> claStr=new ArrayList<>();
                    for (UserClass userClass : classList) {
                        claStr.add(userClass.getCid());
                    }
                    entityWrapper.in("class_id",claStr);
                }
            }
        }
        if(!StringUtils.isEmpty(inputParam.getJurisId())){
            entityWrapper.eq("juris_id",inputParam.getJurisId());
        }
        if(!StringUtils.isEmpty(inputParam.getSchoolId())){
             entityWrapper.eq("school_id",inputParam.getSchoolId());
        }
        if(!StringUtils.isEmpty(inputParam.getClassId())){
            entityWrapper.eq("class_id",inputParam.getClassId());
        }

        entityWrapper.eq("status",1);
        entityWrapper.orderBy("create_time",false);
        entityWrapper.orderBy("id",true);
        //查分页
        if(inputParam!=null && inputParam.getPage()!=null && inputParam.getSize()!=null
                && inputParam.getPage()>0 &&  inputParam.getSize()>0){
            Page<User> page = new Page<User>(inputParam.getPage(), inputParam.getSize());
            List<User> tempList = this.baseMapper.selectPage(page,entityWrapper);
            Integer total = this.baseMapper.selectCount(entityWrapper);

            Map<String, Object> resultMap = new HashMap<String, Object>();
            //结果处理的时候，若是老师管理界面  显示班级，需要重新查询
            tempList = teacherListFormat(user.getRoleType(),tempList);
            resultMap.put("rows", tempList);
            resultMap.put("total", total);
            return ResponseInfo.success(resultMap);
        }else {//查全部
            List<User> tempList = this.baseMapper.selectList(entityWrapper);
            return ResponseInfo.success(tempList);
        }
    }

    /**
     * @Author: HuangHaiShui 
     * @Description: 结果处理的时候，若是老师管理界面  显示班级，需要重新查询
     * @Date: 17:24 2021/7/16
     * @param roleType: 
     * @param tempList:
     * @return: List<User>
     **/
    private  List<User> teacherListFormat(Integer roleType, List<User> tempList){
        if(roleType.equals(Role.TEACHER)){
            for (User tea : tempList) {
                List<Classinfo> list = classinfoService.findByUserId(tea.getId());
                if(list.size()>0){
                    tea.setClassinfoList(list);
                }
            }
        }
        return tempList;
    }
    
    @Override
    public Map dele(User user) {
        if(!StringUtils.isEmpty(user.getId())){
            //设置为不可用
            user.setStatus(0);
            this.baseMapper.updateById(user);
        }
        return ResponseInfo.success(null);
    }

    @Override
    public Map info(InputParam inputParam) {
        if(StringUtils.isEmpty(inputParam.getUserId())){
            return ResponseInfo.error("参数校验失败");
        }
        User user = this.selectById(inputParam.getUserId());
        Map<String, Object> resultMap = new HashMap<String, Object>();
        ArrayList roleArr = new ArrayList<String>();
        roleArr.add(Role.roleFlag.get(user.getRoleType()));
        resultMap.put("roles",roleArr );//为了便于后续升级，设置为数组
        resultMap.put("user", user);

        if(user.getRoleType().equals(Role.SUPER)){
            //超管 查询辖区、学校、班级
            List<Jurisdiction> list = jurisdictionService.findBySuper();
            resultMap.put("areas", list);
        }else if(user.getRoleType().equals(Role.AREA)){
            //区管 查询 学校 班级
            List<School> schoolList = schoolService.findSchoolAndClassByJurisId(user.getJurisId());
            resultMap.put("areas", schoolList);
        }else if(user.getRoleType().equals(Role.SCHOOL)){
            //校管 查询 班级
            Classinfo classinfo = new Classinfo();
            classinfo.setSchoolId(user.getSchoolId());
            Map res
                    = classinfoService.list(classinfo, inputParam);
            resultMap.put("areas", res.get("data"));
        }else if(user.getRoleType().equals(Role.TEACHER)){
            //老师 查询 班级
            List<Classinfo> classinfoList = classinfoService.findByUserId(inputParam.getUserId());
            resultMap.put("areas", classinfoList);
        }
        return ResponseInfo.success(resultMap);
    }

    @Override
    public Map resetPass(InputParam inputParam) {
        if(inputParam !=null && !StringUtils.isEmpty(inputParam.getUserId())
            && !StringUtils.isEmpty(inputParam.getId())){
            User user = new User();
            user.setId(inputParam.getId());
            user.setPassword(Md5Util.getMD5("123456"));
            this.baseMapper.updateById(user);
            return ResponseInfo.success("密码已重置为：123456");
        }else {
            return ResponseInfo.error("参数校验错误");
        }
    }

    @Override
    public Map modifyPass(InputParam inputParam) {
        if(inputParam !=null
                && !StringUtils.isEmpty(inputParam.getUserId())
                && !StringUtils.isEmpty(inputParam.getOldPass())
                && !StringUtils.isEmpty(inputParam.getPass())){
            User temp = this.baseMapper.selectById(inputParam.getUserId());
            if(inputParam.getPass().length()>16){
                return ResponseInfo.error("密码长度不能超过16位");
            }
            String oldStr = Md5Util.getMD5(inputParam.getOldPass());
            if(oldStr.equals(temp.getPassword())) {
                User user = new User();
                user.setId(inputParam.getUserId());
                user.setPassword(Md5Util.getMD5(inputParam.getPass()));
                this.baseMapper.updateById(user);
                return ResponseInfo.success("密码已修改为：" + inputParam.getPass());
            }else{
                return ResponseInfo.error("旧密码输入错误");
            }
        }else {
            return ResponseInfo.error("参数校验错误");
        }
    }
    @Value("${upload.folderName}")
    private String folderName;
    @Override
    public Map photo(MultipartFile file, InputParam inputParam) throws IOException {
        String filename = FileUpload.writeUploadFile(file,folderName,"photo");
        //TODO:每次上传前，先删除旧图片
        User user = new User();
        user.setId(inputParam.getUserId());
        user.setPhotoUrl(filename);
        this.baseMapper.updateById(user);
        return ResponseInfo.success(filename);
    }

    @Override
    public Map getById(InputParam inputParam) {

        //用户的辖区，校区在return的时候，从静态数据里取名称
        User user = this.baseMapper.selectById(inputParam.getId());
        if(user.getRoleType().equals(Role.TEACHER)){
            //老师要查所属班级
            List<Classinfo> list = classinfoService.findByUserId(user.getId());
            if(list.size()>0){
                user.setClassinfoList(list);
            }
        }

        return ResponseInfo.success(user);
    }



    @Override
    public void exportByCid(HttpServletResponse response, InputParam inputParam) throws IOException {
        if(StringUtils.isEmpty(inputParam.getClassId())) {
            return ;
        }
        //查询班级名称
        Classinfo classinfo = classinfoService.selectById(inputParam.getClassId());

        //查询该班级下的所有学生
        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();
        entityWrapper.eq("status",1);
        entityWrapper.eq("class_id",inputParam.getClassId());
        entityWrapper.eq("role_type",4);
        entityWrapper.orderBy("create_time",false);
        List<User> userList = this.baseMapper.selectList(entityWrapper);
        List<UserDto> userDtoList = new ArrayList<>();
        for (User user : userList) {
            UserDto udt = new UserDto();
            udt.setClassName(classinfo.getName());
            BeanUtils.copyProperties(user,udt);
            userDtoList.add(udt);
        }
        //导出excel
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        //设置头居中
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //内容策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //设置 水平居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(classinfo.getName(), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");
        // 这里需要设置不关闭流
        EasyExcel.write(response.getOutputStream(), UserDto.class)
                .autoCloseStream(Boolean.FALSE)
                .registerWriteHandler(horizontalCellStyleStrategy)
                .sheet(classinfo.getName()).doWrite(userDtoList);

    }

    @Override
    public Map getTeachers(InputParam inputParam) {
        if(StringUtils.isEmpty(inputParam.getUserId()) ||
                inputParam==null) {
            return ResponseInfo.error(SystemParam.ERROR_PARAMS);
        }
        //当前用户的信息
        User temp = this.baseMapper.selectById(inputParam.getUserId());
        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();

        if(!StringUtils.isEmpty(inputParam.getSchoolId())){
            entityWrapper.eq("school_id",inputParam.getSchoolId());
        }
        if(temp.getRoleType().equals(Role.SCHOOL)){
            entityWrapper.eq("school_id",temp.getSchoolId());
        }
        entityWrapper.eq("role_type",3);
        entityWrapper.eq("status",1);
        entityWrapper.orderBy("create_time",false);
        List<User> tempList = this.baseMapper.selectList(entityWrapper);
        tempList = teacherListFormat(3,tempList);
        return ResponseInfo.success(tempList);
    }

    @Override
    public Map getStuByClassId(InputParam inputParam) {
        if(StringUtils.isEmpty(inputParam.getClassId()) ||
                inputParam==null) {
            return ResponseInfo.error(SystemParam.ERROR_PARAMS);
        }
        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();
        entityWrapper.eq("class_id",inputParam.getClassId());
        entityWrapper.eq("role_type",4);
        entityWrapper.eq("status",1);
        entityWrapper.orderBy("create_time",false);

        Page<User> page = new Page<User>(inputParam.getPage(), inputParam.getSize());
        List<User> tempList = this.baseMapper.selectPage(page,entityWrapper);
        Integer total = this.baseMapper.selectCount(entityWrapper);

        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("rows", tempList);
        resultMap.put("total", total);
        return ResponseInfo.success(resultMap);
    }
    @Override
    public  List<User>  getStusByClassId(InputParam inputParam) {
        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();
        entityWrapper.eq("class_id",inputParam.getClassId());
        entityWrapper.eq("role_type",4);
        entityWrapper.eq("status",1);
        entityWrapper.orderBy("create_time",false);
        List<User> tempList = this.baseMapper.selectList(entityWrapper);
        return tempList;
    }

    @Override
    public Integer getCountByClassId(String clsId) {
        EntityWrapper<User> entityWrapper = new EntityWrapper<User>();
        entityWrapper.eq("class_id",clsId);
        entityWrapper.eq("role_type",4);
        entityWrapper.eq("status",1);

        Integer total = this.baseMapper.selectCount(entityWrapper);
        return total;
    }

    @Override
    public List<User> getTeaByClsId(String clsId) {
        if(StringUtils.isEmpty(clsId) ) {
            return null;
        }else{
            return this.baseMapper.getTeaByClsId(clsId);
        }
    }

    @Override
    public void deleByJruisId(InputParam inputParam) {
        if(!StringUtils.isEmpty(inputParam.getJurisId()) ) {
            this.baseMapper.deleByParam(inputParam);
        }
    }
    @Override
    public void deleBySchoolId(InputParam inputParam) {
        if(!StringUtils.isEmpty(inputParam.getSchoolId()) ) {
            this.baseMapper.deleByParam(inputParam);
        }
    }
    @Override
    public void deleByClsId(InputParam inputParam) {
        if(!StringUtils.isEmpty(inputParam.getClassId()) ) {
            this.baseMapper.deleByParam(inputParam);
        }
    }

    @Override
    public Map importByCid(MultipartFile file, InputParam inputParam) throws IOException {
        if(StringUtils.isEmpty(inputParam.getClassId()) ||
                inputParam==null|| file.getSize()<10) {
            return ResponseInfo.error(SystemParam.ERROR_PARAMS);
        }else{
            InputStream inputStream = file.getInputStream();
            List<Object> tempList = EasyExcel.read(inputStream)
                    .head(UserTem.class)
                    // 设置sheet,默认读取第一个
                    .sheet()
                    // 设置标题所在行数
                    .headRowNumber(1)
                    .doReadSync();//获取数据

            //去重,防止文件里的账号出现相同
            ArrayList importList = new ArrayList(tempList.size());
            for(int i=0;i<tempList.size();i++){
                if(!importList.contains(tempList.get(i))) {
                    importList.add(tempList.get(i));
                }
            }

            //查询班级
            Classinfo classinfo = classinfoService.selectById(inputParam.getClassId());
            if(classinfo == null) {
                return ResponseInfo.error("班级不存在");
            }
            List<User> batch = new ArrayList<>();
            String msg="导入失败的账号如下：";
            for (Object o : importList) {
                UserTem temp = (UserTem) o;
                User user = new User();
                user.setClassId(inputParam.getClassId());
                user.setSchoolId(classinfo.getSchoolId());
                user.setJurisId(classinfo.getJurisId());
                user.setId("u-"+UUID.randomUUID().toString().replaceAll("-",""));
                user.setPassword(Md5Util.getMD5("123456"));
                user.setCreateTime(new Date());
                user.setStatus(1);
                user.setRoleType(Role.STUDENT);
                user.setName(temp.getName());
                user.setTel(temp.getTel());
                user.setAccount(temp.getAccount());
                List<User> userArr = this.baseMapper.selectList(new EntityWrapper<User>()
                        .eq("account", user.getAccount()));
                if(userArr.size()>0){
                        msg+=user.getAccount()+";";
                }else {
                    batch.add(user);
                }
            }
            if(batch.size()>0){
                this.insertBatch(batch);
            }
            msg = msg.substring(0,msg.length()-1);
            return ResponseInfo.success(msg+"。");
        }
    }

    @Override
    public Integer getCountByParam(InputParam inputParam) {
        EntityWrapper entityWrapper = new EntityWrapper<User>();
        if(!StringUtils.isEmpty(inputParam.getJurisId())) {
            entityWrapper.eq("juris_id", inputParam.getJurisId());
        }
        if(!StringUtils.isEmpty(inputParam.getSchoolId())) {
            entityWrapper.eq("school_id", inputParam.getSchoolId());
        }
        entityWrapper.eq("role_type",Role.STUDENT);
        entityWrapper.eq("status",1);
        Integer count = this.baseMapper.selectCount(entityWrapper);
        return count;
    }


    /**
     * @Author: HuangHaiShui
     *
     * @Description:获取用户的角色类型
     *    1 区管   2 校管  3 教师  4 学生  5 超管
     * @Date: 9:49 2021/7/15
     * @param userId:
     * @return: Integer
     **/
    private Integer getUserRole(String userId){
        if(StringUtils.isEmpty(userId)) {
            return 999;
        }
        User user = this.baseMapper.selectById(userId);
        return user.getRoleType();
    }


}
